{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import PVGeo\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import vista\n",
    "\n",
    "print('NumPy Version: %s' % np.__version__)\n",
    "print('PVGeo Version: %s' % PVGeo.__version__)\n",
    "print('vista Version: %s' % vista.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Welcome to PVGeo\n",
    "\n",
    "Thanks for checking out this notebook! We hope this provides some insight on how you can get started using PVGeo in your Python (3) routines. Let's get started!\n",
    "\n",
    "At the top of this notebook, we import `numpy` and `PVGeo` and display the current environment's version of thos packages. Since PVGeo is still in its infancy, feature development is rapid and new versions get deployed very often. With this in mind, be sure to keep the PVGeo in your environment up to date! \n",
    "\n",
    "A simple way to update PVGeo from your Jupyter Notebook:\n",
    "\n",
    "```py\n",
    "!pip install --upgrade PVGeo\n",
    "```\n",
    "\n",
    "We have placed some data files in the `data/` directory for you to use. The remainder of this notebook will explore a few examples loading, filtering, and writing out data using a combination of `PVGeo` and `vista`\n",
    "\n",
    "\n",
    "## 1. Introduction to PVGeo\n",
    "\n",
    "### What is PVGeo?\n",
    "\n",
    "- **Python** package for 3D/4D geovisualization.\n",
    "- Create compelling and **integrated visualizations**.\n",
    "- Built upon **VTK**, a scalable and well-maintained visualization library.\n",
    "- Extends geovisualization into **ParaView**, **VTK.js**, and **Virtual Reality**.\n",
    "- **Open-source** and automatically deployed.\n",
    "\n",
    "![expansion-diagram](./images/expansion-diagram.png)\n",
    "\n",
    "\n",
    "### Abstract\n",
    "\n",
    "PVGeo is an open-source Python package for geoscientific visualization and analysis, harnessing an already powerful software platform: the Visualization Toolkit (VTK) and its front-end application, [ParaView](http://paraview.org). The VTK software platform is well-maintained, contains an expansive set of native functionality, and provides a robust foundation for scientific visualization, yet the development of tools compatible for geoscience data and models has been limited. As a software extension package to VTK and ParaView, PVGeo addresses the lack of geoscientific compatibility by creating a framework for geovisualization. This framework is a set of tools for visually integrating geoscience data and models directly within ParaView's graphical user interface, simplifying the required routines to make compelling visualizations of geoscientific datasets. PVGeo aims to make the process of importing data into ParaView simple and fluid for users while providing a guide for contributions avoiding the typical, ambitious programming endeavor of building ParaView plugins. The PVGeo package is available for download on PyPI (pip install PVGeo), [documented online](http://pvgeo.org), and [open-source on GitHub](https://github.com/OpenGeoVis/PVGeo) for community-driven development.\n",
    "\n",
    "\n",
    "### PVGeo Resources\n",
    "\n",
    "- [Brief demo page](http://demo.pvgeo.org)\n",
    "- [Slcak community](http://slack.pvgeo.org)\n",
    "- [The code](https://github.com/OpenGeoVis/PVGeo)\n",
    "- [Use examples in ParaView](http://pvgeo.org/examples/about-examples/)\n",
    "- [Nitty gritty code docs](http://docs.pvgeo.org)\n",
    "- [Vimeo video examples](https://vimeo.com/user82050125)\n",
    "\n",
    "\n",
    "### Take aways\n",
    "\n",
    "- Join [PVGeo on Slack](http://slack.pvgeo.org)\n",
    "    - The slack workspace is for anyone using ParaView for geovisualization\n",
    "- [Presentation at AGU in December 2018](http://pvgeo.org/overview/agu-2018/)\n",
    "- ParaView natively extends into VR (dynamically linked)\n",
    "- VTK and ParaView are incredibly scalable\n",
    "- PVGeo is Python based and open-source\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Filtering Data with PVGeo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Table to Points\n",
    "\n",
    "Let's go ahead and load a simple file that has XYZ coordinates and a boolean array for fault presence. This point cloud makes some sort of regular grid, but we have forgotten the deatials of the cell spacings and local coordinate rotations.\n",
    "\n",
    "We will read in this data with pandas and send it to the PVGeo filter `PointsToPolyData` to create a `vista.PolyData` object (essentially a point cloud)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "points = pd.read_csv('data/fault_points.csv')\n",
    "points[0:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Convert to vista.PolyData (this assumes first three columns are XYZ)\n",
    "vtkpoints = PVGeo.pointsToPolyData(points)\n",
    "vtkpoints"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that we have a `vista.PolyData` object now which allows us to do all types of immediate plotting of our data. First, lets threshold our points as the point cloud has a bunch of zeros and ones throughout the dataspace to describe the presence of a fault. \n",
    "\n",
    "To threshold the points, we call the `threshold` filter directly on our data object and pass the thresholding value.\n",
    "\n",
    "We can then plot the result by calling the `plot` function. (Note: change the `notebook` parameter to `False` for an interactive window)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "vtkpoints.plot(clim=[0,1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Points to Voxelized Volume\n",
    "\n",
    "The above figure is pretty cools! But its a point cloud which means out filtering options are pretty limited. Fortunately, we know that the point cloud represents some sort of regularlized gridded volume of data and `PVGeo` has a filter to recover that volume. This will allow further volumetric operations can be performed with other `PVGeo` or VTK filters.\n",
    "\n",
    "Remember that these points are rotated and we do not know the cell sizes... this is okay! The `VoxelizePoints` filter from PVGeo will handle the recovory of the coordinate rotation and grid our data **without** running an interpolation scheme. The `VoxelizePoints` filter assumes that the points are structure on some rotated XY-plane with regular cell spacings and does the rest on its own! Check out [`VoxelizePoints` code docs](http://docs.pvgeo.org/en/latest/content/PVGeo/filters/voxelize.html#voxelize-points) for more details."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# The full pipeline method\n",
    "print('Voxelizing... ', end='')\n",
    "voxelizer = PVGeo.filters.VoxelizePoints()\n",
    "grid = voxelizer.Apply(vtkpoints)\n",
    "print('done.')\n",
    "\n",
    "# Output the results\n",
    "print('Recovered Angle (deg.): %.3f' % voxelizer.GetRecoveredAngle())\n",
    "print('Recovered Cell Sizes: (%.2f, %.2f, %.2f)' % voxelizer.GetSpacing())\n",
    "grid"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# A simpler method to voxelize\n",
    "# grid = PVGeo.filters.VoxelizePoints().Apply(vtkpoints)\n",
    "# grid"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we have a volumetric dataset in the form of a `vista.UnstructuredGrid`! This means we can perform volumetric operations like slicing, clipping, and the works!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Slice Volumetric Data\n",
    "\n",
    "Now lets use one of `vista`'s filters to create slices of the thresholded dataset. Specifically, we are using the `slice_orthogonal` filter that will create 3 orthogonal slices through a data volume."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "slices = grid.slice_orthogonal()\n",
    "slices"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Integrated Visualization\n",
    "\n",
    "Up to this point, we have filtered a single dataset and plotted the result by itself; this is usefult, but what if we have all kinds of data we want to throw into one rendering environment? Its pretty easy:\n",
    "\n",
    "For a simple case, see below. Otherwise, move on to our next notebooks that run through bigger datasets and show how to combine data feature like a 3D model with topography surfaces, well trajectories, and more!\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "clip = grid.clip(normal='x').clip(normal='-y').threshold(0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "p = vista.Plotter()\n",
    "p.add_mesh(slices)\n",
    "p.add_mesh(clip)\n",
    "p.show_grid()\n",
    "p.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:dev]",
   "language": "python",
   "name": "dev"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
